home *** CD-ROM | disk | FTP | other *** search
/ Plug-In Power Pack for Netscape Communicator / Plug-In Power Pack for Netscape Communicator.iso / plugins / dataviews / dvtools / examples / programs / dynamic_sd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-08  |  24.6 KB  |  756 lines

  1. #ifndef lint
  2. static char SccsId[]= "@(#)@(#)dynamic_sd.c    1.19  V1.19    3/13/95";
  3. #endif
  4. /*
  5. |    file name - dynamic_sd.c
  6. |=======================================================================
  7. |
  8. |    This example program loads in a single view that contains two
  9. |    subdrawing objects.   After setting up some event handling for
  10. |    menu and two input objects that appear at the bottom of the
  11. |    view, it creates three linked lists which contain (among other
  12. |    things) the data source variables from the main view and the
  13. |    two subdrawing views. The user can then pick on the text toggle
  14. |    menus at the left that toggle between 'Local' and 'Global.'
  15. |    This will specify what kind of mapping there is for each of the
  16. |    data source variables.  The user can then select 'Run' to animate
  17. |    the drawings. There are digit graphs for each of the data source
  18. |    variables so the user can monitor the actual values and see how
  19. |    they change in relation to the mappings.  'Restart' will reset
  20. |    the mappings and start from the beginning again, 'Quit' ends
  21. |    the program.
  22. |
  23. |=======================================================================
  24. */
  25. #include <windows.h>
  26. /*
  27.  *  DV-Tools header files
  28.  */
  29. #include "std.h"                /* <stdio.h> etc., scalar & macro definitions */
  30. #include "dvstd.h"              /* public types & constants */
  31. #include "dvtools.h"            /* constants used by T routines */
  32. #include "dvGR.h"               /* constants used by window mgt & GR routines */
  33. #include "VOstd.h"              /* constants used by VO & VOob routines */
  34. #include "Tfundecl.h"           /* T routines (screens, drawports & views) */
  35. #include "VOfundecl.h"          /* VO routines (objects) */
  36. #include "VUerfundecl.h"        /* VUer routines (event handling routines) */
  37. #include "VPfundecl.h"          /* VP routines (put info for dgp & vdp) */
  38.  
  39. /* Constants */
  40. #define  DVPATH            (char *)NULL
  41. #define  DISPFORMS_STB     (char *)NULL
  42. #define  DVDEVICE          (char *)NULL
  43. #define  DVCOLORTABLE      (char *)NULL
  44. #define  VIEW_NAME         "dyn_sd.v"
  45. #define  SCREEN_VIEWPORT   (RECTANGLE *)NULL
  46. #define  QUIT_BUTTON       1
  47. #define  RESTART_BUTTON    2
  48. #define  RUN_BUTTON        3
  49. #define  START_INPUT       1
  50. #define  END_INPUT         2
  51. #define  INITIAL_DQ_SIZE   6
  52. #define  ITER_BUFSIZE      10
  53.  
  54. #define  TERMINATE         0xffff /* must be different from INPUT_* values */
  55.  
  56. /* Structure used to create a linked list of data source variables */
  57. typedef struct lnklst
  58. {
  59.   char *dsname;                 /* Data source name                    */
  60.   DSVAR dsvar;                  /* Data source variable                */
  61.   char *dsvname;                /* Data source variable name           */
  62.   float mapped;                 /* If YES, dsvar is mapped to top view */
  63.   float oldmap;                 /* Used to test if mapping has changed */
  64.   struct lnklst *next;          /* Pointer to next item in list        */
  65. } LNKLST;
  66.  
  67.  
  68. /* Globals */
  69. int MainSelection;
  70. VIEW MainView;
  71. char start_iter[ITER_BUFSIZE], end_iter[ITER_BUFSIZE];
  72. DV_POINT StartFocus, EndFocus;
  73. OBJECT MainScreen, MainDrawing, Sd1, Sd2, StartTxtInp, EndTxtInp;
  74. OBJECT StartBorder, EndBorder;
  75. LNKLST *MainDsvList, *Sd1DsvList, *Sd2DsvList;
  76. DRAWPORT MainDp;
  77.  
  78. /* Global forward function declarations */
  79. ADDRESS GetDsVars V_P_((DATASOURCE ds, DSVAR dsvar, ADDRESS argblock));
  80. void DestroyList V_P_((LNKLST *list));
  81. DSVAR GetDsvByName V_P_((LNKLST *list, char *dsname, char *dsvname));
  82. int RemapDsvars V_P_((OBJECT sd, LNKLST *from, LNKLST *to));
  83. void RebindToggleInputs V_P_((LNKLST *list, OBJECT dq));
  84. int HandleIterInput V_P_((OBJECT Client, EVENT_REQUEST Request,
  85.                           int Label, OBJECT Loc, ADDRESS Args));
  86. int HandleMainMenu V_P_((OBJECT Client, EVENT_REQUEST Request,
  87.                          int Label, OBJECT Loc, ADDRESS Args));
  88. void StartEndEventReqs V_P_((void));
  89. int main V_P_((int argc, char *argv[]));
  90.  
  91.  
  92. /*-----------
  93.  *  GetDsVars -- Designed to be called by the TdlForEachVar() traversal
  94.  *    function, this will creates a linked list of LNKLST structures
  95.  *    which stores various bits of information about the dsvar and
  96.  *    the data source name. These lists are used later on for remapping.
  97.  */
  98. ADDRESS 
  99. GetDsVars (ds, dsvar, argblock)
  100.      DATASOURCE ds;
  101.      DSVAR dsvar;
  102.      ADDRESS argblock;
  103. {
  104.   LNKLST **head = (LNKLST **) argblock;
  105.   LNKLST *new_item;
  106.  
  107.   new_item = (LNKLST *) S_ALLOC (sizeof (LNKLST));
  108.   new_item->dsname = TdsGetName (ds);
  109.   new_item->dsvname = TdsvGetName (dsvar);
  110.   new_item->dsvar = dsvar;
  111.   new_item->mapped = (float) NO;
  112.   new_item->oldmap = (float) NO;
  113.   new_item->next = *head;
  114.   *head = new_item;
  115.  
  116.   return V_CONTINUE_TRAVERSAL;
  117. }
  118.  
  119.  
  120. /*-------------
  121.  *  DestroyList -- Traverses linked list, freeing allocated memory
  122.  */
  123. void 
  124. DestroyList (list)
  125.      LNKLST *list;
  126. {
  127.   LNKLST *next;
  128.   while (list)
  129.     {
  130.       next = list->next;
  131.       S_FREE ((ADDRESS) list);
  132.       list = next;
  133.     }
  134. }
  135.  
  136.  
  137. /*--------------
  138.  *  GetDsvByName -- Traverses list and returns the DSVAR
  139.  *    that matches both the data source name and data
  140.  *    source variable name. The data source name is
  141.  *    optional: if it is NULL, then the first DSVAR in
  142.  *    the list that matches dsname is returned. Returns
  143.  *    NULL if no match is found.
  144.  */
  145. DSVAR 
  146. GetDsvByName (list, dsname, dsvname)
  147.      LNKLST *list;
  148.      char *dsname;
  149.      char *dsvname;
  150. {
  151.   for (; list != (LNKLST *) NULL; list = list->next)
  152.     if ((dsname && !strcmp (dsname, list->dsname) &&
  153.          !strcmp (dsvname, list->dsvname)) ||
  154.         (!strcmp (dsvname, list->dsvname)))
  155.       return list->dsvar;
  156.   return (DSVAR) NULL;
  157. }
  158.  
  159.  
  160. /*------------
  161.  * RemapDsvars -- This function checks the map bindings for
  162.  *    each data source variable in the 'from' list. If the
  163.  *    mappings have changed, it then either maps them to the
  164.  *    'to' list of dsvars (mapped == YES), or it unmaps them
  165.  *    so they use their local data source (mapped == NO). It
  166.  *    returns a boolean value of YES or NO whether or not any
  167.  *    mapping was done.
  168.  *
  169.  *     Note that in this example program 'from' will be the
  170.  *    list from the subdrawings, 'to' is from the main view.
  171.  */
  172. int 
  173. RemapDsvars (sd, from, to)
  174.      OBJECT sd;
  175.      LNKLST *from;
  176.      LNKLST *to;
  177. {
  178.   int RemapResult = NO;
  179.  
  180.   for (; from != (LNKLST *) NULL; from = from->next)
  181.     if (from->mapped != from->oldmap)
  182.       {
  183.         RemapResult = YES;
  184.         if (from->mapped == (float) YES)
  185.           /* Map the dsvar to get its values from top level dsvar */
  186.           VOsdSetDsvMapping (sd, from->dsvar,
  187.                              GetDsvByName (to, from->dsname, from->dsvname));
  188.         else
  189.           /* Unmap the dsvar to get its values from its local data source */
  190.           VOsdSetDsvMapping (sd, from->dsvar, (DSVAR) NULL);
  191.         from->oldmap = from->mapped;
  192.       }
  193.   return RemapResult;
  194. }
  195.  
  196.  
  197. /*-------------------
  198.  * RebindToggleInputs -- This function gets the text toggle
  199.  *    input objects (which toggle between 'Local' and 'Global')
  200.  *    and the polygon 'arrow' objects (which have visibility
  201.  *    dynamics attached to them and are used to visually
  202.  *    indicate the relationship between dsvars when mapping is
  203.  *    'Global'), and rebinds them to the 'mapped' field for each
  204.  *    dsvar. It also adds each arrow polygon to the dq object
  205.  *    that is passed in (see comment below in main() about the
  206.  *    ArrowDq). Handles to the text toggle objects and the arrow
  207.  *    objects are gotten by adding either a '.map' or '.arrow'
  208.  *    extension to the dsvar's name and using that name in
  209.  *    TdrGetNamedObject();
  210.  */
  211. void 
  212. RebindToggleInputs (list, dq)
  213.      LNKLST *list;
  214.      OBJECT dq;
  215. {
  216.   int NumVars;
  217.   char objname[32];
  218.   ADDRESS *VarList;
  219.   OBJECT object;
  220.   VARDESC vdp;
  221.  
  222.   for (list = list; list != (LNKLST *) NULL; list = list->next)
  223.     {
  224.       /* Rebind to toggle input objects first */
  225.       strcpy (objname, list->dsvname);
  226.       strcat (objname, ".map");
  227.       object = TdrGetNamedObject (MainDrawing, objname);
  228.       if (object)
  229.         {
  230.           VOinGetVarList (object, &VarList, &NumVars);
  231.           TvdPutBuffer (VarList[0], (ADDRESS) & (list->mapped));
  232.         }
  233.  
  234.       /* Rebind to 'arrow' dynamic polygon objects next */
  235.       strcpy (objname, list->dsvname);
  236.       strcat (objname, ".arrow");
  237.       object = TdrGetNamedObject (MainDrawing, objname);
  238.       if (object)
  239.         {
  240.           vdp = VOvdGetVdp (VOttVd (VOdyGetDataObj (VOobDyGet (object),
  241.                             V_DYN_VISIBILITY,
  242.                             1)));
  243.           TvdPutBuffer (vdp, (ADDRESS) & (list->mapped));
  244.           VOdqAdd (dq, TOP, object);
  245.         }
  246.     }
  247. }
  248.  
  249.  
  250. /*----------------
  251.  * HandleIterInput -- This routine is called by the Event Handler
  252.  *    when the user picks on one of the two text input objects
  253.  *    that control the 'Start' and 'End' iterations. It
  254.  *    activates the input object and draws a border around it.
  255.  *    When the user is finished, the border is erased, and some
  256.  *    checking is done for reasonable values for the start and
  257.  *    end iterations. Also, if the user has gone backwards in
  258.  *    the iteration, the data source is reset, or if the user
  259.  *    has skipped some iterations, the data source is read
  260.  *    until it matches the start iteration.
  261.  */
  262. /*ARGSUSED*/
  263. int 
  264. HandleIterInput (Client, Request, Label, Loc, Args)
  265.      OBJECT Client;
  266.      EVENT_REQUEST Request;
  267.      int Label;
  268.      OBJECT Loc;
  269.      ADDRESS Args;
  270. {
  271.   int i, oldstart, newstart, oldend, newend, er;
  272.   char *CurrValue, OldStart[ITER_BUFSIZE], OldEnd[ITER_BUFSIZE];
  273.   OBJECT location, inp, border;
  274.   WINEVENT *we;
  275.  
  276.   if (Label == START_INPUT)
  277.     {
  278.       CurrValue = start_iter;
  279.       border = StartBorder;
  280.       inp = StartTxtInp;
  281.     }
  282.   else
  283.     {
  284.       CurrValue = end_iter;
  285.       border = EndBorder;
  286.       inp = EndTxtInp;
  287.     }
  288.  
  289.   /* Save the old values */
  290.   oldstart = atoi (start_iter);
  291.   strcpy (OldStart, start_iter);
  292.   oldend = atoi (end_iter);
  293.   strcpy (OldEnd, end_iter);
  294.  
  295.   TdpDrawObject (MainDp, border);
  296.   VOinState (inp, ACTIVE);
  297.  
  298.   /* Set new value to be nothing */
  299.   CurrValue[0] = '\0';
  300.   TdpDrawNextObject (MainDp, inp);
  301.  
  302.   FOREVER
  303.   {
  304.     location = VOloWinEventPoll (V_WAIT);
  305.     switch (VOloType (location))
  306.       {
  307.       case V_EXPOSE:
  308.         TscRedraw (MainScreen, VOloRegion (location));
  309.         strcpy (start_iter, "");
  310.         TdpDrawObject (MainDp, inp);
  311.         TdpDrawObject (MainDp, border);
  312.         break;
  313.  
  314.       case V_RESIZE:
  315.         TscReset (MainScreen);
  316.         StartEndEventReqs ();
  317.         VOinState (inp, ACTIVE);
  318.         break;
  319.  
  320.       case V_KEYPRESS:
  321.         we = (WINEVENT *) VOloWinEventGet (location);
  322.         if (Label == START_INPUT)
  323.           {
  324.             we->loc.x = StartFocus.x;
  325.             we->loc.y = StartFocus.y;
  326.           }
  327.         else
  328.           {
  329.             we->loc.x = EndFocus.x;
  330.             we->loc.y = EndFocus.y;
  331.           }
  332.  
  333.         TloWinEventSetup (location, we, MainScreen, MainDp);
  334.         break;
  335.       }
  336.  
  337.     er = VUerHandleLocEvent (location);
  338.     if (er == INPUT_DONE)
  339.       break;
  340.     else if (er == TERMINATE)
  341.       return TERMINATE;
  342.   }
  343.  
  344.   /* User has hit a return, restore old value */
  345.   if (strlen (CurrValue) == 0)
  346.     {
  347.       strcpy (CurrValue, OldStart);
  348.       TdpDrawNextObject (MainDp, inp);
  349.     }
  350.  
  351.   /* Tidy programmers that we are, let's clean up after ourselves... */
  352.   TdpEraseObject (MainDp, border);
  353.   VOinState (inp, INACTIVE);
  354.  
  355.   /* Let's check the iterations for some reasonable values... */
  356.   newstart = atoi (start_iter);
  357.   newend = atoi (end_iter);
  358.  
  359.   /* NG, so reset the values... */
  360.   if (newend <= newstart)
  361.     {
  362.       strcpy (start_iter, OldStart);
  363.       TdpDrawNextObject (MainDp, StartTxtInp);
  364.       strcpy (end_iter, OldEnd);
  365.       TdpDrawNextObject (MainDp, EndTxtInp);
  366.     }
  367.  
  368.   /*
  369.    * User wants to rewind data, so close and reopen the data source
  370.    * and read up to just before the new start iteration.
  371.    */
  372.   if (newstart < oldstart)
  373.     {
  374.       TviCloseData (MainView);
  375.       TviOpenData (MainView);
  376.       for (i = 0; i < newstart - 1; i++)
  377.         TviReadData (MainView);
  378.     }
  379.   else if ((newstart - oldend) > 1)
  380.     for (i = oldend; i < newstart - 1; i++)
  381.       TviReadData (MainView);
  382.  
  383.   return INPUT_USED;
  384. }
  385.  
  386. /*----------------
  387.  *  HandleMainMenu -- Handles the 'Quit', 'Restart' and 'Run' buttons.
  388.  */
  389. int 
  390. HandleMainMenu (Client, Request, Label, Loc, Args)
  391.      OBJECT Client;
  392.      EVENT_REQUEST Request;
  393.      int Label;
  394.      OBJECT Loc;
  395.      ADDRESS Args;
  396. {
  397.   int i, start, end, diff;
  398.   int remap1, remap2;
  399.   LNKLST *list;
  400.  
  401.   switch (MainSelection)
  402.     {
  403.     case RUN_BUTTON:
  404.       /*
  405.        *  Call RemapDsvars to make sure mappings are up to date.  If
  406.        *  some mapping has occurred, we need to redraw the drawport
  407.        *  for the new mappings to take effect.
  408.        */
  409.       remap1 = RemapDsvars (Sd1, Sd1DsvList, MainDsvList);
  410.       remap2 = RemapDsvars (Sd2, Sd2DsvList, MainDsvList);
  411.       if (remap1 || remap2)
  412.         TdpDraw (MainDp);
  413.  
  414.       /*
  415.        *  Now iterate the number of times as specified by start_iter
  416.        *  and end_iter, reading data each time and updating both the
  417.        *  dynamic subdrawings and the 'Start' and 'End' input objects.
  418.        */
  419.       start = atoi (start_iter);
  420.       end = atoi (end_iter);
  421.       diff = end - start;
  422.  
  423.       for (i = 0; i < diff; i++)
  424.         {
  425.           /* Update start and end variables for the start and end
  426.              input objects to reflect this run */
  427.           sprintf (start_iter, "%d", ++start);
  428.           sprintf (end_iter, "%d", ++end);
  429.  
  430.           /* Do the read and update the screen. The routine will
  431.              TdpDrawNext will update the changes made to the start
  432.              and end input object variables. */
  433.           TviReadData (MainView);
  434.           TdpDrawNext (MainDp);
  435.         }
  436.  
  437.       /*
  438.        *  Set next iteration interval to be 1 more that what was just
  439.        *  down, i.e. 1-10 => 11-20, not 10-19
  440.        */
  441.       sprintf (start_iter, "%d", ++start);
  442.       TdpDrawNextObject (MainDp, StartTxtInp);
  443.       sprintf (end_iter, "%d", (++end));
  444.       TdpDrawNextObject (MainDp, EndTxtInp);
  445.       break;
  446.  
  447.     case RESTART_BUTTON:
  448.       /*
  449.        *  Set main view's and subdrawing's dsvars to be local, unmap
  450.        *  them, and set their initial values to be 0.0
  451.        */
  452.       for (list = Sd1DsvList; list != (LNKLST *) NULL; list = list->next)
  453.         {
  454.           list->mapped = (float) NO;
  455.           list->oldmap = (float) NO;
  456.           VOsdSetDsvMapping (Sd1, list->dsvar, (DSVAR) NULL);
  457.           TdsvSetValue (list->dsvar, (double) 0.0, 0, 0);
  458.         }
  459.       for (list = Sd2DsvList; list != (LNKLST *) NULL; list = list->next)
  460.         {
  461.           list->mapped = (float) NO;
  462.           list->oldmap = (float) NO;
  463.           VOsdSetDsvMapping (Sd2, list->dsvar, (DSVAR) NULL);
  464.           TdsvSetValue (list->dsvar, (double) 0.0, 0, 0);
  465.         }
  466.       for (list = MainDsvList; list != (LNKLST *) NULL; list = list->next)
  467.         TdsvSetValue (list->dsvar, (double) 0.0,(int)0, (int)0);
  468.  
  469.       strcpy (start_iter, "1");
  470.       strcpy (end_iter, "10");
  471.  
  472.       /* Well, lets restart everything... */
  473.       TviCloseData (MainView);
  474.       TviOpenData (MainView);
  475.       TdpDraw (MainDp);
  476.       break;
  477.  
  478.     case QUIT_BUTTON:
  479.       DestroyList (MainDsvList);
  480.       DestroyList (Sd1DsvList);
  481.       DestroyList (Sd2DsvList);
  482.       TdpDestroy (MainDp);
  483.       TviDestroy (MainView);
  484.       TscCloseCurrentScreen ();
  485.       TTerminate ();
  486.       return TERMINATE;
  487.     }
  488.  
  489.   return INPUT_USED;
  490. }
  491.  
  492.  
  493. /*--------------------
  494.  *   StartEndEventReqs -- Post rectangle edge event requests for the
  495.  *              area around the text input objects. The text
  496.  *              input objects represent start and end iterations
  497.  *              respectively.  The event requests will be
  498.  *              reposted when a resize event occurs.
  499.  */
  500. void
  501. StartEndEventReqs ()
  502. {
  503.   RECTANGLE area, delta;
  504.  
  505.   /*
  506.    *  Obtain the bounding box of the starting iteration
  507.    *  text input object.  Use this area to post an inside
  508.    *  edge event request and identify the left mouse key
  509.    *  as the selection key.
  510.    */
  511.   VOobBox (StartTxtInp, &area, &delta);
  512.   TdpWorldToScreen (MainDp, &area.ll, &area.ll);
  513.   TdpWorldToScreen (MainDp, &area.ur, &area.ur);
  514.   VUerRectEdgePost ((OBJECT) 1, HandleIterInput,
  515.                     NULL, 0, &area, V_INSIDE, "\001", START_INPUT);
  516.  
  517.   /*
  518.    *  Calculate the text focus point so that the pointer does not
  519.    *  need to be in the text entry input object when entering text.
  520.    *  Also, deactivate the input object until it is selected.
  521.    */
  522.   StartFocus.x = (area.ll.x + area.ur.x) / 2;
  523.   StartFocus.y = (area.ll.y + area.ur.y) / 2;
  524.   VOinState (StartTxtInp, INACTIVE);
  525.  
  526.   /*
  527.    *  Obtain the bounding box of the ending iteration
  528.    *  text input object.  Use this area to post an inside
  529.    *  edge event request and identify the left mouse key
  530.    *  as the selection key.
  531.    */
  532.   VOobBox (EndTxtInp, &area, &delta);
  533.   TdpWorldToScreen (MainDp, &area.ll, &area.ll);
  534.   TdpWorldToScreen (MainDp, &area.ur, &area.ur);
  535.   VUerRectEdgePost ((OBJECT) 1, HandleIterInput,
  536.                     NULL, 0, &area, V_INSIDE, "\001", END_INPUT);
  537.  
  538.   /*
  539.    *  Calculate the text focus point so that the pointer does not
  540.    *  need to be in the text entry input object when entering text.
  541.    *  Also, deactivate the input object until it is selected.
  542.    */
  543.   EndFocus.x = (area.ll.x + area.ur.x) / 2;
  544.   EndFocus.y = (area.ll.y + area.ur.y) / 2;
  545.   VOinState (EndTxtInp, INACTIVE);
  546. }
  547.  
  548.  
  549. /*
  550.  *   MAIN PROGRAM
  551.  */
  552. int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, 
  553.                      LPSTR lpCmdLine, int nCmdShow )
  554. {
  555.   INT argc = 0;
  556.   CHAR **argv;
  557.   /*
  558.    *  program arguments
  559.    *    argv[1] - display device name (default is to use DVDEVICE)
  560.    */
  561.  
  562.   /* Define & initialize device name and view filename */
  563.   char *device_name = DVDEVICE; /* default device name */
  564.   char *view_name = VIEW_NAME;  /* default view name */
  565.  
  566.   int NumVars, er;
  567.   OBJECT ArrowDq, loc, tmpobj;
  568.   ADDRESS *VarList;
  569.   RECTANGLE area, delta;
  570.  
  571.   /*--------------------
  572.    *  Initialization
  573.    *
  574.    *  TInit:  perform the initialization of DV-Tools
  575.    *          TInit reads your configuration file and any
  576.    *          environment variables or logical names set.
  577.    */
  578.   make_argv(&argc,&argv,GetCommandLine());
  579.   TInit( DVPATH, DISPFORMS_STB );
  580.  
  581.   /*
  582.    *  TscOpenSet: open a device as a screen object using
  583.    *              specified attributes
  584.    *  TscErase:   erase the entire screen in the default
  585.    *              background color
  586.    *
  587.    *  Set exposure block to YES to insure the window
  588.    *  is ready for drawing when TdpDraw is called.
  589.    */
  590.   if (argc > 1)
  591.     device_name = argv[1];
  592.   MainScreen = TscOpenSet (device_name, DVCOLORTABLE,
  593.                            V_X_EXPOSURE_BLOCK, YES,
  594.                            V_ACTIVE_CURSOR, V_END_OF_LIST);
  595.   if (!MainScreen)
  596.     {
  597.       printf ("Must specify device on command line or");
  598.       printf (" in DataViews configuration file.\n");
  599.       S_EXIT (EXIT_ERR);
  600.     }
  601.  
  602.   /*
  603.    *  VOscWinEventMask:  sets the screen's window event mask
  604.    */
  605.   VOscWinEventMask ((ULONG) V_KEYPRESS | V_BUTTONPRESS | V_MOTIONNOTIFY
  606.                             | V_EXPOSE | V_RESIZE,
  607.                     (ULONG) 0);
  608.  
  609.   /*
  610.    *   TviLoad:   Load a view in from a file,
  611.    *              the view dyn_sd.v
  612.    */
  613.   MainView = TviLoad (view_name);
  614.   if (!MainView)
  615.     {
  616.       printf ("Could not load view from file ");
  617.       printf ("%s.\n", view_name);
  618.       S_EXIT (EXIT_ERR);
  619.     }
  620.  
  621.   /*
  622.    *  Get a view's drawing object and create drawports based on
  623.    *  defined areas.
  624.    */
  625.   MainDrawing = TviGetDrawing (MainView);
  626.   tmpobj = TdrGetNamedObject (MainDrawing, "main.area");
  627.   VOobBox (tmpobj, &area, &delta);
  628.   MainDp = TdpCreateStretch (MainScreen, MainView, SCREEN_VIEWPORT, &area);
  629.  
  630.   /*
  631.    *  Rebind and set up event handling for 'Quit,' 'Run,' and `Restart' menu.
  632.    */
  633.   tmpobj = TdrGetNamedObject (MainDrawing, "run.menu");
  634.   VOinGetVarList (tmpobj, &VarList, &NumVars);
  635.   TvdPutBuffer (VarList[0], (ADDRESS) & MainSelection);
  636.   VPvdtype ((VARDESC) VarList[0], V_I_TYPE);
  637.   VUerServiceResultPost ((OBJECT) 1, HandleMainMenu,
  638.                          NULL, 0, tmpobj, INPUT_DONE, (int)1);
  639.  
  640.   /*
  641.    *     Get a handle to two text input objects and rebind them to global
  642.    *  program buffers (set the vdp type and dimensions to be thorough). Then
  643.    *  then set their default values.
  644.    *     Next, deactivate them from accepting input and set up an event handler
  645.    *  to handle them when the user selects on either object with the left
  646.    *  mouse button. In this case, the events are based on the particular area
  647.    *  on the screen occupied by the input objects.
  648.    *     And one final touch, the view contains rectangle objects around each
  649.    *  of these input objects which are to be drawn when the user has selected
  650.    *  the object and erased when done.  These objects are deleted from the
  651.    *  drawing (Note that first their reference count is increased so they are
  652.    *  not automatically destroyed when removed from the drawing).  They are
  653.    *  then drawn and erased separately as needed by the function
  654.    *  HandleIterInput().
  655.    */
  656.   StartTxtInp = TdrGetNamedObject (MainDrawing, "start");
  657.   VOinGetVarList (StartTxtInp, &VarList, &NumVars);
  658.   TvdPutBuffer (VarList[0], start_iter);
  659.   VPvdtype ( VarList[0], V_T_TYPE);
  660.   VPvddim ((VARDESC) VarList[0], (int)1, (int)1, (int)ITER_BUFSIZE);
  661.   strcpy (start_iter, "1");
  662.  
  663.   /* Get border rectangle object */
  664.   StartBorder = TdrGetNamedObject (MainDrawing, "start.border");
  665.   VOobReference(StartBorder);
  666.   VOdrObDelete (MainDrawing, StartBorder);
  667.  
  668.   /* Now do the same thing for 'End' input object... */
  669.   EndTxtInp = TdrGetNamedObject (MainDrawing, "end");
  670.   VOinGetVarList (EndTxtInp, &VarList, &NumVars);
  671.   TvdPutBuffer (VarList[0], end_iter);
  672.   VPvdtype ((VARDESC) VarList[0], V_T_TYPE);
  673.   VPvddim ((VARDESC) VarList[0], (int)1, (int)1, (int)ITER_BUFSIZE);
  674.   strcpy (end_iter, "10");
  675.  
  676.   EndBorder = TdrGetNamedObject (MainDrawing, "end.border");
  677.   VOobReference (EndBorder);
  678.   VOdrObDelete (MainDrawing, EndBorder);
  679.  
  680.   StartEndEventReqs ();
  681.  
  682.   /*
  683.    *  Get a handle to the two subdrawing objects and enable their dynamics
  684.    */
  685.   Sd1 = TdrGetNamedObject (MainDrawing, "sd1");
  686.   VOsdSetDynamicFlag (Sd1, SD_DYN_ENABLED);
  687.   Sd2 = TdrGetNamedObject (MainDrawing, "sd2");
  688.   VOsdSetDynamicFlag (Sd2, SD_DYN_ENABLED);
  689.  
  690.   /*
  691.    *  Create three linked lists of data source variables from the two
  692.    *  subdrawing objects and the main view.
  693.   */
  694.   MainDsvList = Sd1DsvList = Sd2DsvList = NULL;
  695.   TdlForEachVar (TviGetDataSourceList (MainView),
  696.                 (TDLFOREACHDSVFUNPTR)GetDsVars, (ADDRESS) & MainDsvList);
  697.   TdlForEachVar (TviGetDataSourceList (VOsdViGet (Sd1)),
  698.                 (TDLFOREACHDSVFUNPTR)GetDsVars, (ADDRESS) & Sd1DsvList);
  699.   TdlForEachVar (TviGetDataSourceList (VOsdViGet (Sd2)),
  700.                 (TDLFOREACHDSVFUNPTR)GetDsVars, (ADDRESS) & Sd2DsvList);
  701.  
  702.   /*
  703.    *  ArrowDq is a container object which will hold the arrow
  704.    *  polygon objects. These objects have visibility dynamics
  705.    *  attached to them, and as such, they need to have their
  706.    *  dynamics updated using TdpDrawNext() or TdpDrawNextObject().
  707.    *  TdpDrawNextObject() is used here because we do not want any
  708.    *  of the subdrawings to update, so by creating a single container
  709.    *  object, we can isolate which dynamics we want updated.
  710.    */
  711.   ArrowDq = VOdqCreate (INITIAL_DQ_SIZE);
  712.  
  713.   /*
  714.    *  Bind the toggle input objects and the dynamic arrows to each dsvar's
  715.    *  'mapped' field in the linked list structure.  This routine also adds
  716.    *  the arrow objects to the ArrowDq.
  717.    */
  718.   RebindToggleInputs (Sd1DsvList, ArrowDq);
  719.   RebindToggleInputs (Sd2DsvList, ArrowDq);
  720.  
  721.   TviOpenData (MainView);
  722.   TscErase (MainScreen);
  723.   TdpDraw (MainDp);
  724.  
  725.   FOREVER
  726.   {
  727.     /* Poll the cursor */
  728.     loc = VOloWinEventPoll (V_WAIT);
  729.     switch (VOloType (loc))
  730.       {
  731.       case V_BUTTONPRESS:
  732.       case V_KEYPRESS:
  733.         /* Update any arrows that may have changed and pass the location object
  734.         |  onto the event handler */
  735.         er = VUerHandleLocEvent (loc);
  736.         if (er != TERMINATE)
  737.           TdpDrawNextObject (MainDp, ArrowDq);
  738.         break;
  739.  
  740.       case V_EXPOSE:
  741.         TscRedraw (MainScreen, VOloRegion (loc));
  742.         break;
  743.  
  744.       case V_RESIZE:
  745.         /* We don't redraw the screen since every V_RESIZE event
  746.          | will be followed by a V_EXPOSE event */
  747.         TscReset (MainScreen);
  748.         StartEndEventReqs ();
  749.         break;
  750.       }
  751.     if (er == TERMINATE)
  752.       break;
  753.   }
  754.   return EXIT_OK;
  755. }
  756.